package com.durian.base.update.proxy.impl

import com.durian.BaseApp
import com.durian.base.update.XUpdate
import com.durian.base.update.entity.*
import com.durian.base.update.proxy.DownloadApkCallBack
import com.durian.base.update.proxy.IUpdateDownloader
import com.durian.base.update.proxy.IUpdateRequest
import com.durian.base.utils.ToolUtils
import java.lang.Exception
import java.lang.RuntimeException

open class DefaultUpdateDownloader : IUpdateDownloader {

    private var downloadNotification : DownloadNotification? = null

    override fun startDownload(versionEntity: VersionEntity, updateRequest: IUpdateRequest) {
        XUpdate.getLog().i("startDownload()---启动下载服务")
        val downloadCallBack = FileDownloadApkCallBack(updateRequest)
        val apkFile = updateRequest.getUpdateChecker()?.doCreateApkFile(XUpdate.getContext(), versionEntity)
        if (apkFile == null) {
            downloadCallBack.onError(Throwable("下载路径不正确！"))
            return
        }
        val checker = updateRequest.getUpdateChecker() ?: return
        val downloadEntity = DownloadEntity(apkFile, versionEntity)
        downloadCallBack.onStart()
        if (checker.doCheckApkVerification(downloadEntity,false)) {//不需要下载直接安装
            downloadCallBack.onFinish(downloadEntity)
            XUpdate.getLog().i("doCheckApkVerification()---文件校验通过")
            XUpdate.getLog().i("doStartDownloadApk()---文件不需要下载直接安装")
        }else{
            try {
                downloadEntity.apkFile.safeDelete()
                XUpdate.getLog().i("downloadApk()---开始下载文件[${apkFile.absolutePath}]")
                updateRequest.getHttpRequest()?.downloadApk(downloadEntity,downloadCallBack)
            } catch (e: Exception) {
                XUpdate.getLog().i("downloadApk()---下载异常：${e.message}")
                e.printStackTrace()
                downloadCallBack.onError(e)
            }
        }
    }

    private fun initDownloadNotification(){
        downloadNotification = DownloadNotification(XUpdate.getContext())
    }

    private inner class FileDownloadApkCallBack(val request : IUpdateRequest) : DownloadApkCallBack {

        private var mOldRate = 0

        fun onStart() {
            BaseApp.handler().post { doOnStart() }
        }

        private fun doOnStart(){
            if (request.getUpdateConfig()?.showNotification() == true){
                initDownloadNotification()
                downloadNotification?.createNotification()
            }
            request.getUpdateListener()?.doDownloadApkBefore()
            XUpdate.getLog().i("FileDownloadApkCallBack.onStart()---开始下载文件...")
        }

        override fun onFinish(downloadEntity: DownloadEntity) {
            BaseApp.handler().post { doOnFinish(downloadEntity) }
        }

        private fun doOnFinish(downloadEntity: DownloadEntity){
            try {
                if (request.getUpdateConfig()?.showNotification() == true){
                    downloadNotification?.showSuccessNotification()
                }
                val updateListener = request.getUpdateListener()?:return
                val updateChecker = request.getUpdateChecker()?:return
                val installController = request.getUpdateInstallController()?:return
                XUpdate.getLog().i("FileDownloadApkCallBack.onFinish()---文件下载完成")
                if (updateChecker.doCheckApkVerification(downloadEntity,true)){
                    XUpdate.getLog().i("FileDownloadApkCallBack.onFinish()---文件校验通过！")
                    updateListener.installNewVersion(installController,downloadEntity)
                    XUpdate.getLog().i("installNewVersion()---安装文件")
                    request.getUpdateListener()?.doDownloadApkAfter()
                }else{
                    downloadEntity.apkFile.safeDelete()
                    downloadEntity.apkFileTemp.safeDelete()
                    XUpdate.getLog().i("FileDownloadApkCallBack.onFinish()---文件校验失败！")
                    throw RuntimeException("文件下载不全！")
                }
            }catch (e:Exception){
                XUpdate.getLog().e("FileDownloadApkCallBack.onFinish()---下载异常：${e.message}")
                e.printStackTrace()
                onError(e)
            }finally {
                close()
            }
        }

        override fun onProgress(current: Long, total: Long) {
            BaseApp.handler().post { doOnProgress(current,total) }
        }

        private fun doOnProgress(current: Long, total: Long){
            //做一下判断，防止自回调过于频繁，造成更新通知栏进度过于频繁，而出现卡顿的问题。
            val cur = if (current < 0) 0 else current
            val to = if (total < cur) cur else total
            val rate = (cur * 1.0f * 100 / to).toInt()
            if (mOldRate != rate) {
                XUpdate.getLog().i("FileDownloadApkCallBack.onProgress(${cur},${to},${rate})")
                if (request.getUpdateConfig()?.showNotification() == true){
                    downloadNotification?.showProgressNotification(rate)
                }
                request.getUpdateListener()?.doDownloadApkProgress(rate,cur,to)
                mOldRate = rate
            }
        }

        override fun onError(throwable: Throwable?) {
            BaseApp.handler().post { doOnError(throwable) }
        }

        private fun doOnError(throwable: Throwable?){
            try {
                if (request.getUpdateConfig()?.showNotification() == true){
                    downloadNotification?.showErrorNotification()
                }
                request.getUpdateListener()?.doDownloadApkException(XUpdateException(throwable, XUpdateDownloadErrorCode.Unknown))
                XUpdate.getLog().e("下载错误")
            }catch (e:Exception){
                e.printStackTrace()
                XUpdate.getLog().e(ToolUtils.collectErrorInfo(e))
            }finally {
                close()
            }
        }

    }

    private fun close(){
        XUpdate.setDownloading(false)
    }

}